package ghostcat.algorithm.traversal {
	import flash.geom.Point;

	public class AStar extends Traversal {
		protected var heapOpenList:BinaryHeap;

		public function AStar(param1:MapModel, param2:int = 5000) {
			super(param1, param2);
			return;
		} // end function

		override public function find(param1:Point, param2:Point):Array {
			var traversalNode:TraversalNote = null;
			var point:Point = null;
			var arroundPoints:Array = null;
			var arroundPoint:Point = null;
			var arroundTraversalNode:TraversalNote = null;
			var cost:int = 0;
			var totalCost:int = 0;
			this.heapOpenList = new BinaryHeap();
			this.heapOpenList.sortMetord = sortMetord;
			mapModel.reset();
			var _try:int = 0;
			this.openNote(param1, 0, 0, null);
			while (this.heapOpenList.length > 0) {

				if (++_try > this.maxTry) {
					return null;
				}
				traversalNode = this.heapOpenList.shift();
				this.closeNote(traversalNode);
				point = traversalNode.point;
				if (mapModel.reachEnd(point, param2)) {
					return this.getPath(param1, traversalNode);
				}
				arroundPoints = mapModel.getArounds(traversalNode.point);
				for each (arroundPoint in arroundPoints) {

					arroundTraversalNode = mapModel.getNode(arroundPoint);
					if (arroundTraversalNode && arroundTraversalNode.noteClosed) {
						continue;
					}
					cost = traversalNode.cost + mapModel.getCostAddon(param1, traversalNode.point, arroundPoint, param2);
					totalCost = cost + mapModel.getScoreAddon(param1, traversalNode.point, arroundPoint, param2);
					if (arroundTraversalNode && arroundTraversalNode.noteOpen) {
						if (cost < arroundTraversalNode.cost) {
							arroundTraversalNode.cost = cost;
							arroundTraversalNode.score = totalCost;
							arroundTraversalNode.parent = traversalNode;
							this.heapOpenList.modify(arroundTraversalNode);
						}
						continue;
					}
					this.openNote(arroundPoint, totalCost, cost, traversalNode);
				}
			}
			return null;
		} // end function

		private function sortMetord(param1:TraversalNote, param2:TraversalNote):Boolean {
			return param1.score < param2.score;
		} // end function

		override protected function openNote(param1:Point, param2:int, param3:int, param4:TraversalNote):void {
			var note:TraversalNote = new TraversalNote();
			note.point = param1;
			note.score = param2;
			note.cost = param3;
			note.parent = param4;
			mapModel.setNode(param1, note);
			this.heapOpenList.push(note);
			return;
		} // end function

	}
}
